home *** CD-ROM | disk | FTP | other *** search
/ MACD 5 / MACD 5.bin / workbench / time / vclock / area.c next >
C/C++ Source or Header  |  1994-01-12  |  15KB  |  491 lines

  1. /* $VER: $Id: area.c,v 1.9 1994/01/12 07:47:46 tf Exp $ © 1992,93 by Tobias Ferber */
  2.  
  3. #include <exec/types.h>
  4. #include <exec/memory.h>
  5. #include <graphics/gfx.h>
  6. #include <graphics/gfxmacros.h>
  7. #include <intuition/intuition.h>
  8. #include <time.h>
  9. #include "timer.h"
  10.  
  11. /* globals = */
  12. static struct GfxBase *GfxBase;
  13. static struct IntuitionBase *IntuitionBase;
  14. static struct Window *win;
  15. static struct AreaInfo areainfo;
  16. static struct TmpRas tras;
  17. static APTR areabuf= (APTR)NULL;
  18. static PLANEPTR trasbuf= (PLANEPTR)NULL;
  19. static BOOL menuflag= FALSE;
  20.  
  21. /* the following vd_xxxx are all set by rethink_dimensions() */
  22. static short vd_width,   /* current vector digit dimensions */
  23.              vd_height,
  24.              vd_ypos,
  25.              vd_spcx;
  26.  
  27. #define MAXVECTORS (64*6)  /* for the area stuff */
  28. #define AREASIZE ((MAXVECTORS+1) * 5) /* +1 vector for AreaEnd() */
  29. #define TRASSIZE ((win->WScreen->Width/8) * win->WScreen->Height)
  30.  
  31. static struct NewWindow nw= {
  32.   0,0,
  33.   350,55,
  34.   -1,-1,
  35.   CLOSEWINDOW|MENUPICK|NEWSIZE,
  36.   GIMMEZEROZERO|SMART_REFRESH,
  37.   NULL,NULL,
  38.   (UBYTE*)"vClock",
  39.   NULL,NULL,
  40.   130,20,
  41.   -1,-1,
  42.   WBENCHSCREEN
  43. };
  44.  
  45. struct IntuiText quit_text= {
  46.   0,1,JAM1,1,1,NULL,"Quit",   NULL,
  47. };
  48.  
  49. struct MenuItem quit_item= {
  50.   NULL, 0,0, 0,0, ITEMENABLED|HIGHCOMP|ITEMTEXT|COMMSEQ, 0,
  51.   (APTR)&quit_text, NULL, 'Q', NULL, 0
  52. };
  53.  
  54. struct Menu menu= {
  55.   NULL, 0,0, 0,0, MENUENABLED, (BYTE *)"Project", &quit_item, 0,0,0,0
  56. };
  57.  
  58. #define EDGES 8
  59.  
  60. struct ptxy { short x,y; } a,b,c,d,e,f,g, /* segment offset */
  61.                            top[EDGES],
  62.                            bottom[EDGES],
  63.                            left[EDGES],
  64.                            right[EDGES],
  65.                            mid[4];
  66.  
  67. /* Init the vector tables of all segments of a vector digit with
  68.  * width w and height h.  This function will be called when using
  69.  * rethink_dimensions().
  70.  */
  71.  
  72. void init_vectors(short w, short h)
  73. {
  74.   unsigned short dx1= (5*w+4)/8,
  75.                  dx2= (w+1)/2,
  76.                  dx3= (w+4)/8,
  77.                  dx4= (w+8)/16,
  78.                  dy1= (3*h+4)/8,
  79.                  dy2= (h+2)/4,
  80.                  dy3= (h+4)/8,
  81.                  dy4= (h+8)/16;
  82.  
  83.   /* corrections */
  84.  
  85.   dx1= dx4+dx2+dx4;
  86.   dy1= dy4+dy2+dy4;
  87.  
  88. /*
  89.   printf("dx1=%d, dx2=%d, dx3=%d, dx4=%d, "
  90.          "dy1=%d, dy2=%d, dy3=%d, dy4=%d\n",dx1,dx2,dx3,dx4,
  91.                                             dy1,dy2,dy3,dy4 );
  92. */
  93.  
  94.   /* segment offsets */
  95.  
  96.   a.x= dx3+dx4;        a.y= 0;
  97.   b.x= dx3+2*dx4+dx1;  b.y= dy4;
  98.   c.x= dx3+2*dx4+dx1;  c.y= 2*dy4+dy1;
  99.   d.x= dx3+2*dx4;      d.y= 2*dy1+2*dy4;
  100.   e.x= 0;              e.y= 2*dy4+dy1;
  101.   f.x= 0;              f.y= dy4;
  102.   g.x= dx3+2*dx4;      g.y= dy4+dy1;
  103.  
  104.   /* delta values */
  105.  
  106.   top[0].x= dx1;       top[0].y= 0;
  107.   top[1].x= 0;         top[1].y= dy4;
  108.   top[2].x= -dx4;      top[2].y= 0;
  109.   top[3].x= 0;         top[3].y= dy4;
  110.   top[4].x= -dx2;      top[4].y= 0;
  111.   top[5].x= 0;         top[5].y= -dy4;
  112.   top[6].x= -dx4;      top[6].y= 0;
  113.   top[7].x= 0;         top[7].y= -dy4;
  114.  
  115.   right[0].x= dx3;     right[0].y= 0;
  116.   right[1].x= 0;       right[1].y= dy1;
  117.   right[2].x= -dx3;    right[2].y= 0;
  118.   right[3].x= 0;       right[3].y= -dy4;
  119.   right[4].x= -dx4;    right[4].y= 0;
  120.   right[5].x= 0;       right[5].y= -dy2;
  121.   right[6].x= dx4;     right[6].y= 0;
  122.   right[7].x= 0;       right[7].y= -dy4;
  123.  
  124.   left[0].x= dx3;      left[0].y= 0;
  125.   left[1].x= 0;        left[1].y= dy4;
  126.   left[2].x= dx4;      left[2].y= 0;
  127.   left[3].x= 0;        left[3].y= dy2;
  128.   left[4].x= -dx4;     left[4].y= 0;
  129.   left[5].x= 0;        left[5].y= dy4;
  130.   left[6].x= -dx3;     left[6].y= 0;
  131.   left[7].x= 0;        left[7].y= -dy1;
  132.  
  133.   bottom[0].x= dx2;    bottom[0].y= 0;
  134.   bottom[1].x= 0;      bottom[1].y= dy4;
  135.   bottom[2].x= dx4;    bottom[2].y= 0;
  136.   bottom[3].x= 0;      bottom[3].y= dy4;
  137.   bottom[4].x= -dx1;   bottom[4].y= 0;
  138.   bottom[5].x= 0;      bottom[5].y= -dy4;
  139.   bottom[6].x= dx4;    bottom[6].y= 0;
  140.   bottom[7].x= 0;      bottom[7].y= -dy4;
  141.  
  142.   mid[0].x= dx2;       mid[0].y= 0;
  143.   mid[1].x= 0;         mid[1].y= dy3;
  144.   mid[2].x= -dx2;      mid[2].y= 0;
  145.   mid[3].x= 0;         mid[3].y= -dy3;
  146. }
  147.  
  148. /* rethink the vector digit dimensions for the hh:mm:ss display
  149.  * in a rastport of width w and height h and call init_vectors()
  150.  */
  151.  
  152. void rethink_dimensions(void)
  153. {
  154.   short ww= win->Width  - win->BorderLeft - win->BorderRight,
  155.         wh= win->Height - win->BorderTop  - win->BorderBottom;
  156.  
  157.   vd_ypos   = (wh + 7)  / 13;
  158.   vd_spcx   = (ww + 16) / 32;
  159.   vd_height = wh - (2 * vd_ypos) - 4;
  160.   vd_width  = (ww - 9 * vd_spcx) / 6;
  161.  
  162.   init_vectors(vd_width, vd_height);
  163. /*
  164.   printf("vd_ypos=%d, vd_spcx=%d, vd_height=%d, vd_width=%d\n",
  165.     vd_ypos,vd_spcx,vd_height,vd_width);
  166. */
  167. }
  168.  
  169. /* Missing in the graphics.library ? */
  170.  
  171. void AreaPolyDraw(struct RastPort *rp, short x,
  172.                                        short y,
  173.                                        short edges,
  174.                                        short dxy[])
  175. { short e;
  176.   AreaMove(rp,x,y);
  177.   for(e=0;e<edges;e++)
  178.   { x+= dxy[2*e];
  179.     y+= dxy[2*e+1];
  180.     AreaDraw(rp,x,y);
  181.   }
  182. }
  183.  
  184. /* Render a vector digit at (xpos|ypos) into the given RastPort rp.
  185.  * Note that this RastPort *MUST* have a fully initialized TmpRas
  186.  * and AreaInfo structure.
  187.  * If you pass a 'smart' value >=0 to this function, it only
  188.  * changes the differing segments between `digit' and `smart'.
  189.  * SET segments will be filled with rp's FgPen, UNSET segments
  190.  * using the BgPen.
  191.  * Passed digit and smart values *MUST* be in [0..15], except
  192.  * smart which can be -1 for non-smart rendering.
  193.  */
  194.  
  195. void render_vecdigit(struct RastPort *rp,short xpos,
  196.                                          short ypos,
  197.                                          int digit,
  198.                                          int smart)
  199. { static const UBYTE seglist[17][8]= {
  200.   /* a b c d e f g */
  201.   { 1,1,1,1,1,1,0 },    /* 0                      */
  202.   { 0,1,1,0,0,0,0 },    /* 1      aaaaaaaaaa      */
  203.   { 1,1,0,1,1,0,1 },    /* 2   ff  aaaaaaaa  bb   */
  204.   { 1,1,1,1,0,0,1 },    /* 3   fff          bbb   */
  205.   { 0,1,1,0,0,1,1 },    /* 4   fff          bbb   */
  206.   { 1,0,1,1,0,1,1 },    /* 5   fff          bbb   */
  207.   { 1,0,1,1,1,1,1 },    /* 6   ff            bb   */
  208.   { 1,1,1,0,0,0,0 },    /* 7       gggggggg       */
  209.   { 1,1,1,1,1,1,1 },    /* 8   ee  gggggggg  cc   */
  210.   { 1,1,1,1,0,1,1 },    /* 9   eee          ccc   */
  211.   { 1,1,1,0,1,1,1 },    /* A   eee          ccc   */
  212.   { 0,0,1,1,1,1,1 },    /* B   eee          ccc   */
  213.   { 1,0,0,1,1,1,0 },    /* C   ee  dddddddd  cc   */
  214.   { 0,1,1,1,1,0,1 },    /* D      dddddddddd      */
  215.   { 1,0,0,1,1,1,1 },    /* E                      */
  216.   { 1,0,0,0,1,1,1 } };  /* F                      */
  217.  
  218.   if(smart<0)
  219.   { if(seglist[digit][0]) AreaPolyDraw(rp,xpos+a.x,ypos+a.y,EDGES,top);
  220.     if(seglist[digit][1]) AreaPolyDraw(rp,xpos+b.x,ypos+b.y,EDGES,right);
  221.     if(seglist[digit][2]) AreaPolyDraw(rp,xpos+c.x,ypos+c.y,EDGES,right);
  222.     if(seglist[digit][3]) AreaPolyDraw(rp,xpos+d.x,ypos+d.y,EDGES,bottom);
  223.     if(seglist[digit][4]) AreaPolyDraw(rp,xpos+e.x,ypos+e.y,EDGES,left);
  224.     if(seglist[digit][5]) AreaPolyDraw(rp,xpos+f.x,ypos+f.y,EDGES,left);
  225.     if(seglist[digit][6]) AreaPolyDraw(rp,xpos+g.x,ypos+g.y,4,mid);
  226.     AreaEnd(rp);
  227.   }
  228.   else
  229.   { BYTE apen= rp->FgPen;
  230.     if(seglist[digit][0] &! seglist[smart][0])
  231.       AreaPolyDraw(rp,xpos+a.x,ypos+a.y,EDGES,top);
  232.     if(seglist[digit][1] &! seglist[smart][1])
  233.       AreaPolyDraw(rp,xpos+b.x,ypos+b.y,EDGES,right);
  234.     if(seglist[digit][2] &! seglist[smart][2])
  235.       AreaPolyDraw(rp,xpos+c.x,ypos+c.y,EDGES,right);
  236.     if(seglist[digit][3] &! seglist[smart][3])
  237.       AreaPolyDraw(rp,xpos+d.x,ypos+d.y,EDGES,bottom);
  238.     if(seglist[digit][4] &! seglist[smart][4])
  239.       AreaPolyDraw(rp,xpos+e.x,ypos+e.y,EDGES,left);
  240.     if(seglist[digit][5] &! seglist[smart][5])
  241.       AreaPolyDraw(rp,xpos+f.x,ypos+f.y,EDGES,left);
  242.     if(seglist[digit][6] &! seglist[smart][6])
  243.       AreaPolyDraw(rp,xpos+g.x,ypos+g.y,4,mid);
  244.     AreaEnd(rp);
  245.  
  246.     SetAPen(rp,rp->BgPen);
  247.     if(seglist[smart][0] &! seglist[digit][0])
  248.       AreaPolyDraw(rp,xpos+a.x,ypos+a.y,EDGES,top);
  249.     if(seglist[smart][1] &! seglist[digit][1])
  250.       AreaPolyDraw(rp,xpos+b.x,ypos+b.y,EDGES,right);
  251.     if(seglist[smart][2] &! seglist[digit][2])
  252.       AreaPolyDraw(rp,xpos+c.x,ypos+c.y,EDGES,right);
  253.     if(seglist[smart][3] &! seglist[digit][3])
  254.       AreaPolyDraw(rp,xpos+d.x,ypos+d.y,EDGES,bottom);
  255.     if(seglist[smart][4] &! seglist[digit][4])
  256.       AreaPolyDraw(rp,xpos+e.x,ypos+e.y,EDGES,left);
  257.     if(seglist[smart][5] &! seglist[digit][5])
  258.       AreaPolyDraw(rp,xpos+f.x,ypos+f.y,EDGES,left);
  259.     if(seglist[smart][6] &! seglist[digit][6])
  260.       AreaPolyDraw(rp,xpos+g.x,ypos+g.y,4,mid);
  261.     AreaEnd(rp);
  262.     SetAPen(rp,apen);
  263.   }
  264. }
  265.  
  266. void set_vclock(struct RastPort *rp, int h, int m, int s, int clr)
  267. {
  268.   static int _hh= -1, _h= -1,
  269.              _mm= -1, _m= -1,
  270.              _ss= -1, _s= -1;
  271.  
  272.   int hh= h/10,
  273.       mm= m/10,
  274.       ss= s/10;
  275.  
  276.   h%=10;
  277.   m%=10;
  278.   s%=10;
  279.  
  280.   if(clr) _hh= _h= _mm= _m= _ss= _s= -1;
  281.  
  282.   if(_hh!=hh)
  283.   { render_vecdigit(rp,vd_spcx,vd_ypos,hh,_hh);
  284.     _hh=hh;
  285.   }
  286.   if(_h!=h)
  287.   { render_vecdigit(rp,vd_width+2*vd_spcx,vd_ypos,h,_h);
  288.     _h=h;
  289.   }
  290.   if(_mm!=mm)
  291.   { render_vecdigit(rp,2*vd_width+4*vd_spcx,vd_ypos,mm,_mm);
  292.     _mm=mm;
  293.   }
  294.   if(_m!=m)
  295.   { render_vecdigit(rp,3*vd_width+5*vd_spcx,vd_ypos,m,_m);
  296.     _m=m;
  297.   }
  298.   if(_ss!=ss)
  299.   { render_vecdigit(rp,4*vd_width+7*vd_spcx,vd_ypos,ss,_ss);
  300.     _ss=ss;
  301.   }
  302.   if(_s!=s)
  303.   { render_vecdigit(rp,5*vd_width+8*vd_spcx,vd_ypos,s,_s);
  304.     _s=s;
  305.   }
  306. }
  307.  
  308. /* open the system stuff and allocate needed memory */
  309.  
  310. int open_vectorstuff(void)
  311. { int ok=0;
  312.   if(IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0L))
  313.   { struct Screen s; /* for the Workbench Screen data */
  314.     if(GetScreenData(&s,sizeof(struct Screen),WBENCHSCREEN,NULL))
  315.     { short hc= s.WBorLeft + s.WBorRight,
  316.             vc= s.WBorTop  + s.WBorBottom;
  317.  
  318.       if(nw.Title) vc += s.Font->ta_YSize + 1;
  319.  
  320.       nw.Width  += hc;  nw.MinWidth  += hc;
  321.       nw.Height += vc;  nw.MinHeight += vc;
  322.  
  323.       if(nw.Width  < nw.MinWidth)  nw.Width  = nw.MinWidth;
  324.       if(nw.Height < nw.MinHeight) nw.Height = nw.MinHeight;
  325.  
  326.       if(nw.LeftEdge+nw.Width > s.Width)
  327.       { if(nw.Width > s.Width) nw.Width= s.Width;
  328.         nw.LeftEdge= s.Width-nw.Width;
  329.       }
  330.       if(nw.TopEdge+nw.Height > s.Height)
  331.       { if(nw.Height > s.Height) nw.Height= s.Height;
  332.         nw.TopEdge= s.Height-nw.Height;
  333.       }
  334.     }
  335.     if(GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0L))
  336.     { if(win=(struct Window *)OpenWindow(&nw))
  337.       { if(areabuf= (APTR)AllocMem(AREASIZE,MEMF_PUBLIC|MEMF_CLEAR))
  338.         { if(trasbuf= (PLANEPTR)AllocRaster(win->WScreen->Width,
  339.                                             win->WScreen->Height))
  340.           { InitArea(&areainfo,areabuf,MAXVECTORS);
  341.             win->RPort->AreaInfo=&areainfo;
  342.             win->RPort->TmpRas=(struct TmpRas *)
  343.               InitTmpRas(&tras,trasbuf,TRASSIZE);
  344.             quit_text.ITextFont= win->WScreen->Font;
  345.             quit_item.Height= 2 + win->WScreen->Font->ta_YSize;
  346.             quit_item.Width= 4 * IntuiTextLength(&quit_text);
  347.             menu.Width= quit_item.Width;
  348.             menuflag= SetMenuStrip(win,&menu);
  349.             ok= menuflag ? 1:0;
  350.           }
  351.           else free(areabuf);
  352.         }
  353.         else CloseWindow(win);
  354.       }
  355.       else CloseLibrary(GfxBase);
  356.     }
  357.     else CloseLibrary(IntuitionBase);
  358.   }
  359.   return ok;
  360. }
  361.  
  362. void close_vectorstuff(void)
  363. { if(menuflag && win) ClearMenuStrip(win);
  364.   if(trasbuf) FreeRaster(trasbuf,win->WScreen->Width,
  365.                                  win->WScreen->Height);
  366.   if(areabuf) FreeMem(areabuf,AREASIZE);
  367.   if(win) CloseWindow(win);
  368.   if(GfxBase) CloseLibrary(GfxBase);
  369.   if(IntuitionBase) CloseLibrary(IntuitionBase);
  370. }
  371.  
  372. update_titles(struct Window *w, struct tm *lt)
  373. { static const char *dn[]= { "Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun" },
  374.                     *mn[]= { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug",
  375.                              "Sep","Oct","Nov","Dec" };
  376.  
  377.   static int d= -1, m= -1, y= -1;
  378.   static char wtitle[20];
  379.  
  380.   if(d != lt->tm_mday || m != lt->tm_mon || y != lt->tm_year)
  381.   { d= lt->tm_mday;
  382.     m= lt->tm_mon;
  383.     y= lt->tm_year;
  384.     sprintf(wtitle,"%s %02d-%s-%02d",dn[lt->tm_wday],d,mn[m],y);
  385.     SetWindowTitles(w,wtitle,-1L); /* -1 = old title */
  386.   }
  387. }
  388.  
  389. int do_vclock(short leftedge,
  390.               short topedge,
  391.               short width,
  392.               short height,
  393.               short setpen,
  394.               short unsetpen,
  395.               short outline,
  396.               short backfill,
  397.               short notitle,
  398.               long wflags)
  399.  
  400. { int rc= -1; /* return code; != 0 indicates failure */
  401.  
  402.   nw.LeftEdge= leftedge;
  403.   nw.TopEdge= topedge;
  404.   nw.Width= width;
  405.   nw.Height= height;
  406.   nw.Flags |= wflags;
  407.   if(notitle) nw.Title= (UBYTE *)NULL;
  408.  
  409.   if( open_vectorstuff() )
  410.   { struct timerequest *tr= open_timer(NULL,0L);
  411.     if(tr != (struct timerequest *)NULL)
  412.     { struct MsgPort *tp= tr->tr_node.io_Message.mn_ReplyPort;
  413.       struct RastPort *rp= win->RPort;
  414.       BOOL done= FALSE;
  415.  
  416.       rc= 0;
  417.       queue_timer(tr,1,0);
  418.       rethink_dimensions();
  419.       SetAPen(rp,setpen);
  420.       SetBPen(rp,unsetpen);
  421.       SetOPen(rp,outline);
  422.       SetRast(rp,backfill);
  423.       /*BNDRYOFF(rp);*/
  424.       set_vclock(rp,88,88,88,-1); /* all segments high to init bndry */
  425.  
  426.       while(!done)
  427.       {
  428.         long timersigmask = (1L << tp->mp_SigBit),
  429.              usersigmask  = (1L << win->UserPort->mp_SigBit),
  430.              breaksigmask = SIGBREAKF_CTRL_C,
  431.  
  432.              sig = Wait(timersigmask | usersigmask | breaksigmask);
  433.  
  434.         done |= (sig & breaksigmask);
  435.  
  436.         if(sig & timersigmask)
  437.         {
  438.           while(GetMsg(tp) != (struct Message *)NULL)
  439.             ;
  440.  
  441.           if(CheckIO((struct IORequest *)tr))
  442.           {
  443.             long t;
  444.             struct tm *lt;
  445.             time(&t);
  446.             lt= (struct tm *)localtime(&t);
  447.             set_vclock(rp,lt->tm_hour,lt->tm_min,lt->tm_sec,0);
  448.  
  449.             if(!notitle)
  450.               update_titles(win,lt);
  451.  
  452.             queue_timer(tr,1,0);
  453.           }
  454.         }
  455.         if(sig & usersigmask)
  456.         {
  457.           ULONG class;
  458.           UWORD code;
  459.           struct IntuiMessage *imsg;
  460.           while(imsg= (struct IntuiMessage *)GetMsg(win->UserPort))
  461.           { code= imsg->Code;
  462.             done |= ((class= imsg->Class) == CLOSEWINDOW);
  463.             ReplyMsg((struct Message *)imsg);
  464.  
  465.             switch(class)
  466.             {
  467.               case NEWSIZE:
  468.                 rethink_dimensions();
  469.                 SetRast(rp,backfill);
  470.                 set_vclock(rp,88,88,88,-1);
  471.                 break;
  472.  
  473.               case MENUPICK:
  474.                 while(code != MENUNULL)
  475.                 { struct MenuItem *mi= (struct MenuItem *)ItemAddress(&menu,code);
  476.                   done |= (MENUNUM(code) == 0 && ITEMNUM(code) == 0);
  477.                   code= (mi && mi->NextSelect != code) ? mi->NextSelect : MENUNULL;
  478.                 }
  479.                 break;
  480.             }
  481.           }
  482.         }
  483.       }
  484.       purge_timer(tr);
  485.       close_timer(tr);
  486.     }
  487.     close_vectorstuff();
  488.   }
  489.   return rc;
  490. }
  491.